/*
 * Container.java
 * Created on July 15, 2007, 8:29 PM
 */

package view;

import base.Settings;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import utils.HashSet;
import view.layout.AbstractLayout;
import view.layout.LayoutManager;

/**
 *
 * @author Erol Hira
 */
public class Container extends Canvas implements CommandListener, Constants {
    
    private HashSet components;
    
    private LayoutManager layoutManager;
    
    private boolean focusChanged = true;
    private int focus = -1;
    private int lastFocus = -1;
    
    private Color bgColor;
    
    private byte max_z_order = DEFAULT_Z_ORDER; // greater ordered components drawn first
    
    private SoftMenuButton leftSoftButton;
    private SoftMenuButton rightSoftButton;
    
    
    //----------------------------------------------------------------------
    
    public Container() {
        components = new HashSet();
        layoutManager = new AbstractLayout();
        bgColor = Color.WHITE;
    }        
    
    //----------------------------------------------------------------------
    
    public final void paint(Graphics graphics) {                
                
        System.out.println("paint");
        
        if(focusChanged){
            
            System.out.println("focusChanged");
            
            clearScreen(graphics);
            
            for(int i = 0; i < components.size(); i++){                
                Component component = (Component) components.get(i);
                component.setPaintFlag(true);
            }
        }
                
        System.out.println("clearScreen");

        layoutManager.layoutContainer(this);  

        for(int j = max_z_order; j >= 0; j--){

            for(int i = 0; i < components.size(); i++){                
                Component component = (Component) components.get(i);
                if(component.getZ_order() == j){  

                    //add if focused ...

                    component.paintComponent(graphics);
                    System.out.println("component " + i + " painted");
                }
            }
        }    
        
        if(focusChanged){
            focusChanged = false; 
        }
                                
    }        
    
    public void repaintContainer(){
        repaint();
    }
    
    public void clearScreen(Graphics graphics){
                
        GuiUtils.setColor(graphics, bgColor);
        graphics.fillRect(0, 0, getWidth(), getHeight());                            
    }
    
    //----------------------------------------------------------------------
    
    protected void keyPressed(int keyCode) {
        
        if(Settings.LEFT_CTRL == keyCode && rightSoftButton != null && rightSoftButton.isActive()){
            
            rightSoftButton.undoCtrl();
            
        } else if(Settings.LEFT_CTRL == keyCode && leftSoftButton != null){
                        
            leftSoftButton.doCtrl();
            
        }  else if(Settings.RIGHT_CTRL == keyCode && leftSoftButton != null && leftSoftButton.isActive()) {
        
            leftSoftButton.undoCtrl();
            
        } else if(Settings.RIGHT_CTRL == keyCode && rightSoftButton != null){
            
            rightSoftButton.doCtrl();
            
        } else {
            
            Component comp = getFocusedComponent();
            
            if(comp != null){
                comp.keyPressed(keyCode);
            }
        }                        
    }        
    
    //----------------------------------------------------------------------
    
    public void commandAction(Command command, Displayable displayable) {
    }
    
    //----------------------------------------------------------------------
    
    protected void doFire(){        
    }
    
    public void focusNext(){
        
        if(getFocusableComponentCount() <= 1){
            return;
        }
                
        while(true){
            
            setFocus(focus + 1);
            focus = focus % components.size();   
            
            Component comp = (Component) components.get(focus);
            if(comp.isFocusable()){
                focusOnComponent();
                break;
            }            
        }        
        
        System.out.println("focus : " + getFocusedComponent().getClass().getName());
    }
    
    public void focusPrevious(){
        
        if(getFocusableComponentCount() <= 1){
            return;
        }
        
        while(true){
            
            setFocus(focus - 1);
            focus = focus >= 0 ? focus : 0;
                        
            Component comp = (Component) components.get(focus);
            if(comp.isFocusable()){
                focusOnComponent();
                break;
            }
        }
        
        System.out.println("focus : " + getFocusedComponent().getClass().getName());
    }
    
    public void focusOnComponent(Component component){
        
        if(component.isFocusable() == false){
            System.out.println("component is not focusable !!!!!!!!!  index:" + components.indexOf(component));
        }
                
        setFocus(components.indexOf(component));
        
        focusOnComponent();
    }
    
    private void focusOnComponent(){
        focusChanged = true;
        getLastFocusedComponent().onFocusLost();
        getFocusedComponent().onFocus();
        repaintContainer();
    }
    
    public void focusLast(){
        focus = lastFocus;
        focusChanged = true;
        getFocusedComponent().onFocus();
        repaintContainer();
    }
    
    private Component getFocusedComponent(){  
        
        if(focus < 0){
            return null;
        } else {
            return (Component) components.get(focus);
        }        
    }
    
    public boolean isFocused(Component component){
        return getFocusedComponent().equals(component);
    }
    
    private Component getLastFocusedComponent(){
        
        if(lastFocus < 0){
            return getFocusedComponent();
        } else {
            return (Component) components.get(lastFocus);
        }
    }
    
    private int getFocusableComponentCount(){
        
        int cnt = 0;
        for(int i = 0; i < components.size(); i++){
            Component comp = (Component) components.get(i);
            if(comp.isFocusable()){
                cnt ++;
            }
        }
        
        return cnt;
    }
    
    public void setFirstFocusableComponent(){
        
        focus = -1;
        
        for(int i = 0; i < components.size(); i++){
            Component comp = (Component) components.get(i);
            if(comp.isFocusable()){
                focus = i;
                return;
            }
        }
    }
    
    protected void setFocus(int focus){
        lastFocus = this.focus;
        this.focus = focus;
    }
    
    public void undoSoftButtons(){
        if(leftSoftButton != null){
            leftSoftButton.undoCtrl();
        }
        
        if(rightSoftButton != null){
            rightSoftButton.undoCtrl();
        }
    }
    
    //----------------------------------------------------------------------
    
    public Container reset(){
        
        setFirstFocusableComponent();
        
        return this;
    }
    
    public void passivateSoftButtons(){
        
        if(leftSoftButton != null){
            leftSoftButton.setActive(false);
        }
        
        if(rightSoftButton != null){
            rightSoftButton.setActive(false);
        }
    }
    
    //----------------------------------------------------------------------
    
    /**
     *  removes this component out from this container 
     */
    public void removeComponent(Component component){
        components.remove(component);
    }
    
    public void removeComponent(int indexOfComponent){
        components.remove(indexOfComponent);
    }
    
    public void removeAll(){
        components.removeAll();
    }
    
    public void add(Component component){
        
        if(component.getZ_order() > max_z_order){
            max_z_order = component.getZ_order();
        }
        
        components.add(component);
        component.setContainer(this);
    }
    
    public void add(Component component, int index){
        
    }
    
    public void add(Component component, Constraints constraints){
        add(component);
        component.setConstraints(constraints);
    }
    
    public void add(Component component, Constraints constraints, int index){
        
    }
    
    public void addLeftSoftButton(SoftMenuButton leftSoftButton){
        this.leftSoftButton = leftSoftButton;
        add(leftSoftButton);
    }
    
    public void addRightSoftButton(SoftMenuButton rightSoftButton){
        this.rightSoftButton = rightSoftButton;
        add(rightSoftButton);        
    }
    
    public Component getComponent(int index){
        return null;
    }
    
    public int getComponentCount(){
        return components.size();
    }
    
    public HashSet getComponents(){
        return components;
    }
    
    public LayoutManager getLayoutManager() {
        return layoutManager;
    }

    public void setLayoutManager(LayoutManager layoutManager) {
        this.layoutManager = layoutManager;
    }
    
    //------------------------------------------------------------------- 
    
    /**
     *  returns the canvas heigth excluded from soft buttons 
     */
    public int getCanvasContentHeight(){
        return getHeight() - SoftMenuButton.softButtonHeight;
    }
    
    //------------------------------------------------------------------- 
    
    public int getHeight(){
        return super.getHeight();
    }
    
    public int getWidth(){
        return super.getWidth();
    } 

    public Color getBgColor() {
        return bgColor;
    }

    public void setBgColor(Color bgColor) {
        this.bgColor = bgColor;
    }
    
}
